
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Random;
import java.util.InputMismatchException;
/**
 *
 * @author Alejo
 */
public class Banco {

   private static boolean bandera;
   //private static ArrayList<Cliente> eventos = new ArrayList<Cliente>();
   private static Cliente clientetemp = new Cliente(0,0,true);  
   private static Cliente clientetemp2 = new Cliente(0,0,true);

   
   
   public static void main(String[] args) {
            
         ImpleArray<Cliente> ventanilla1 = new ImpleArray<Cliente>(), ventanilla2 = new ImpleArray<Cliente>(), ventanilla3 = new ImpleArray<Cliente>(), ventanilla4 = new ImpleArray<Cliente>(); 
       
        ///Para probar con listas ciculares comentar linea anterior y descomentar la siguiente linea por favor
       
       // ImpleCircular<Cliente> ventanilla1 = new ImpleCircular<Cliente>(), ventanilla2 = new ImpleCircular<Cliente>(), ventanilla3 = new ImpleCircular<Cliente>(), ventanilla4 = new ImpleCircular<Cliente>(); 
       
         VectorHeap<Cliente> eventos = new VectorHeap<Cliente>();
         
        Random rand = new Random();
         int tiempod, tiempoac, tsa,tsa2,tsa3,tsa4 = 0;
         int acumulador = 0;
         int nclientes = 0;
         int opcion;
         
         tiempoac = 0;
         tsa= 0;
         tsa2= 0;
         tsa3= 0;
         tsa4= 0;
         do{
                   opcion = (int)verificar(1);
                    if (opcion <= 0 && opcion != -1 || opcion < tiempoac || opcion > 480) {
                            System.out.println("\nERROR: ~~> Tiempo invalido");
                            }
                    else {
                            if (opcion != -1){
                               tiempod = (rand.nextInt(29)+1);
                               eventos.add(new Cliente(opcion,tiempod,true));
                               tiempoac = opcion;
                               
                            }
                         }
                    
        }while(opcion!=-1);       
         System.out.println((eventos));
   if ( !eventos.isEmpty()){
        do{
          //clientetemp = eventos.get(0);
         // linea para utilizar colo con prioridad   
         clientetemp = eventos.getFirst();
         //System.out.println(clientetemp);
         //System.out.println(eventos);
         if (clientetemp.isEntrada()){
             System.out.println(("Buscar ventanilla")); 
             
             if (ventanilla1.size() <= ventanilla2.size() && ventanilla1.size() <= ventanilla3.size() && ventanilla1.size() <= ventanilla4.size() && ventanilla1.size() < 10){
                 ventanilla1.offer(clientetemp);
                 if (!(tsa - (clientetemp.getTi()) < 0)){
                  tsa = tsa - (clientetemp.getTi());
                 }
                 clientetemp.setTs(clientetemp.getTi() + clientetemp.getTt() + tsa );
                 clientetemp.setEntrada(false);
                 //lineas agregadas para utilizar colas con prioridad
                 eventos.add(clientetemp);
                 eventos.remove();
                 //eventos.remove(0);
                 clientetemp.setTe(clientetemp.getTs() - clientetemp.getTi());
                 tsa = clientetemp.getTs();
                 clientetemp.setVentanilla(1);
                 System.out.println("Cliente entro en ventanilla 1 al minuto "+clientetemp.getTi());
                // addSalida(clientetemp.getTs(),clientetemp);
                 nclientes = nclientes + 1;
             }
             else if (ventanilla2.size() <= ventanilla1.size() && ventanilla2.size() <= ventanilla3.size() && ventanilla2.size() <= ventanilla4.size() && ventanilla2.size() < 10){
                 ventanilla2.offer(clientetemp);
                 if (!(tsa2 - (clientetemp.getTi()-1) < 0)){
                  tsa2 = tsa2 - (clientetemp.getTi()-1);
                 }
                 clientetemp.setTs(clientetemp.getTi() + clientetemp.getTt() + tsa2 );
                 clientetemp.setEntrada(false);                     
                  //lineas agregadas para utilizar colas con prioridad
                 eventos.add(clientetemp);
                 eventos.remove();
                 
                 //eventos.remove(0);
                 clientetemp.setTe(clientetemp.getTs() - clientetemp.getTi());
                 tsa2 = clientetemp.getTs();
                 clientetemp.setVentanilla(2);
                  System.out.println("Cliente entro en ventanilla 2 al minuto "+clientetemp.getTi());
                 //addSalida(clientetemp.getTs(),clientetemp);
                nclientes = nclientes + 1;
             }
             else if (ventanilla3.size() <= ventanilla2.size() && ventanilla3.size() <= ventanilla1.size() && ventanilla3.size() <= ventanilla4.size() && ventanilla3.size() < 10){
                 ventanilla3.offer(clientetemp);
                 if (!(tsa3 - (clientetemp.getTi()-1) < 0)){
                  tsa3 = tsa3 - (clientetemp.getTi()-1);
                 }
                 clientetemp.setTs(clientetemp.getTi() + clientetemp.getTt() + tsa3 );
                 clientetemp.setEntrada(false);                     
                 
                  //lineas agregadas para utilizar colas con prioridad
                 eventos.add(clientetemp);
                 eventos.remove();
                 //eventos.remove(0);
                 clientetemp.setTe(clientetemp.getTs() - clientetemp.getTi());
                 tsa3 = clientetemp.getTs();
                 clientetemp.setVentanilla(3);
                 System.out.println("Cliente entro en ventanilla 3 al minuto "+clientetemp.getTi());
                 //addSalida(clientetemp.getTs(),clientetemp);
                 nclientes = nclientes + 1;
             }
             else if (ventanilla4.size() <= ventanilla2.size() && ventanilla4.size() <= ventanilla3.size() && ventanilla4.size() <= ventanilla1.size() && ventanilla4.size() < 10){
                 ventanilla4.offer(clientetemp);
                 if (!(tsa4 - (clientetemp.getTi()-1) < 0)){
                  tsa4 = tsa4 - (clientetemp.getTi()-1);
                 }
                 clientetemp.setTs(clientetemp.getTi() + clientetemp.getTt() + tsa4 );
                 clientetemp.setEntrada(false);                     
                 
                  //lineas agregadas para utilizar colas con prioridad
                 eventos.add(clientetemp);
                 eventos.remove();
                 //eventos.remove(0);
                 clientetemp.setTe(clientetemp.getTs() - clientetemp.getTi());
                 tsa4 = clientetemp.getTs();
                 clientetemp.setVentanilla(4);
                 System.out.println("Cliente entro en ventanilla 4 al minuto "+clientetemp.getTi());
                 //addSalida(clientetemp.getTs(),clientetemp);
                 nclientes = nclientes + 1;
             }     
             else if(ventanilla1.size() ==10 && ventanilla2.size() ==10 && ventanilla3.size() ==10 && ventanilla4.size() ==10 ){
                 System.out.println("Ventanillas llenas no se puede atender entrada de cliente ");
                 eventos.remove();
             }
//System.out.println((eventos));
         }
        //clientetemp = eventos.get(0);
         // linea para utilizar colo con prioridad
        clientetemp = eventos.getFirst();
         if (!(clientetemp.isEntrada())){
             System.out.println("Salida de ventanilla");
             if (clientetemp.getVentanilla() == 1){
                 ventanilla1.poll();
                 acumulador = acumulador + clientetemp.getTe();
                 // linea agregada para colas con prioridad
                 eventos.remove();
                 
                 //eventos.remove(0);
                 
                 System.out.println("Salida de "+clientetemp);
             }
             if (clientetemp.getVentanilla() == 2){
                 ventanilla2.poll();
                  acumulador = acumulador + clientetemp.getTe();
                 // linea agregada para colas con prioridad
                 eventos.remove();
                 
                 //eventos.remove(0);
                 
                 System.out.println(clientetemp);
             }
             if (clientetemp.getVentanilla() == 3){
                 ventanilla3.poll();
                  acumulador = acumulador + clientetemp.getTe();
                 // linea agregada para colas con prioridad
                 eventos.remove();
                 
                 //eventos.remove(0);
                 
                 System.out.println(clientetemp);
             }
             if (clientetemp.getVentanilla() == 4){
                 ventanilla4.poll();
                  acumulador = acumulador + clientetemp.getTe();
                 // linea agregada para colas con prioridad
                 eventos.remove();
                 
                 //eventos.remove(0);
                 
                 System.out.println(clientetemp);
             }
         }
         
        }while(!eventos.isEmpty());
   }
       //System.out.println((eventos));
        System.out.println();
        System.out.println();
        if (nclientes!=0){
        acumulador = acumulador/nclientes;}
        
       System.out.println(("La cantidad promedio de minutos de espera es de: " + acumulador +" minutos."));
    }
  
    /**
     * Procedimiento que permite agregar un evento de salida de un cliente, a la lista de eventos.
     * @param tiempo Se necesita el tiempo de entrada del cliente para determinar la posicion en la lista de eventos.
     * @param eventon Se necesita el cliente al cual se le agregara su evento de salida.
     */
//    public static void addSalida(int tiempo, Cliente eventon){
//          boolean controli = true;
//         for (int i = 0; i < eventos.size(); i++) {
//            clientetemp2 = eventos.get(i);
//            //System.out.println(clientetemp2.isEntrada());
//         if (controli){
//            if (clientetemp2.isEntrada()){
//                 if (tiempo < clientetemp2.getTi()){
//                   eventos.add(i, eventon);
//                   // System.out.println("ingreso evento salida con ti "+clientetemp2.getTi());
//
//                   controli = false;
//                }
//             }
//            if (!(clientetemp2.isEntrada())){
//                  if (tiempo < clientetemp2.getTs()){
//                      eventos.add(i, eventon);
//                     // System.out.println("ingreso evento salida con ts "+clientetemp2.getTs());
//
//                      controli = false;
//                        }
//             }
//            
//            
//         }  
//         
//         }
//         if (controli){
//            eventos.add(eventon);
//            //System.out.println("ingreso evento por fuera de for");
//            }
//        // 
//      }
    
    /**
     * Procedimiento que permite determinar si lo ingresado por teclado fue un numero o no, de no ser un numero muestra un mensaje de error
     * @param op Parametro que permite asignar un mensaje de ingreso, dependiendo el caso
     * @return devuelve  el valor double del numero ingresado por el usuario.
     */
    public static double verificar(int op){
        Scanner ingreso = new Scanner(System.in);
        double num = 0;
	if(op == 0)
			System.out.println("Ingrese su opcion por favor");
        if (op ==1)
                        System.out.println("Ingrese minuto de llegada debe ser mayor a o igual a una cantidad antes ingresada y debe encontrarse entre 1 y 480  , para finalizar ingresos  ingrese -1 porfavor ");
        try{
            num = ingreso.nextDouble();
        }
        catch(InputMismatchException exception){
                System.out.println("\nERROR: ~~> Dato invalido. ingrese un numero\n");
                bandera = true;
        }
        finally{
            ingreso.nextLine();//Atrapar el ENTER
        }
        return num;
    }
}
